package com.yx.cloud.network.ble.yg;

import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;

import com.iot.common.utils.Base64Util;
import com.iot.common.utils.LogUtils;
import com.yx.cloud.network.ble.BleDataHandler;
import com.yx.cloud.network.ble.Cmd;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.UUID;

public class YGBleDataHandler extends BleDataHandler {
    UUID UUID_NOTIFY_DESCRIPTOR;
    public YGBleDataHandler() {
        UUID_SERVICE = UUID.fromString("00009E40-0000-1000-8000-00805f9b34fb");
        UUID_WRITE_CHARACTERISTIC = UUID.fromString("00001011-0000-1000-8000-00805f9b34fb");
        UUID_NOTIFY_CHARICTERISTICE = UUID.fromString("00001015-0000-1000-8000-00805f9b34fb");
        UUID_NOTIFY_DESCRIPTOR=UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
    }

    public boolean validateService(BluetoothGatt gatt) {
        mTransportService = gatt.getService(UUID_SERVICE);
        if (mTransportService == null) {
            LogUtils.i("validateService fail : service not found");
            return false;
        }

        //get characteristic from service
        mWriteCharacteristic = mTransportService.getCharacteristic(UUID_WRITE_CHARACTERISTIC);
        mNotifyCharacteristic = mTransportService.getCharacteristic(UUID_NOTIFY_CHARICTERISTICE);
        LogUtils.i("validateService mWriteCharacteristic :" + mWriteCharacteristic);
        LogUtils.i("validateService mNotifyCharacteristic :" + mNotifyCharacteristic);
        if (mWriteCharacteristic == null || mNotifyCharacteristic == null) {
            LogUtils.i("validateService fail : writeCharacteristic or notifyCharacteristic  not found");
            return false;
        }

        boolean setNotifyResult = gatt.setCharacteristicNotification(mNotifyCharacteristic, true);
        LogUtils.i("setCharacteristicNotification : " + setNotifyResult);
        if (!setNotifyResult) {
            LogUtils.i("validateService fail : enable notification fail,make sure server allow notification");
            return false;
        }

        BluetoothGattDescriptor descriptor = mNotifyCharacteristic.getDescriptor(UUID_NOTIFY_DESCRIPTOR);
        if (descriptor == null) {
            LogUtils.i("validateService fail : descriptor not found ");
            return false;
        }

        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        boolean registNotify = gatt.writeDescriptor(descriptor);

        LogUtils.i("writeDescriptor : " + registNotify);
        return registNotify;
    }

    public List packageData(Cmd command) {
        byte cmd = command.getCmd();
//        byte[] content = command.getContent();

        byte[] content = Base64Util.rawToBase64(command.getContent()).getBytes();
        LogUtils.i("content length:"+ content.length);
        if (content == null) {
            //只有命令的空数据包
            List<YGBleDataPacket> dataPacketList = new ArrayList<>();
            dataPacketList.add(sliceCmd((byte) 1, (byte) 1, cmd, command.getContent()));
            return dataPacketList;
        }

        int remain = content.length;
        int position = 0;
        int currentPackSize;
        byte order = 0;
        byte packageSum = (byte) Math.ceil(content.length * 1f / YGBleDataPacket.REAL_SIZE);

        List<YGBleDataPacket> dataPacketList = new ArrayList<>();
        while (remain > 0) {
            order++;
            if (remain >= YGBleDataPacket.REAL_SIZE) {
                currentPackSize = YGBleDataPacket.REAL_SIZE;
                byte[] pack = new byte[currentPackSize];
                System.arraycopy(content, position, pack, 0, pack.length);
                dataPacketList.add(sliceCmd(order, packageSum, cmd, pack));
            } else {
                currentPackSize = remain;
                byte[] pack = new byte[currentPackSize];
                System.arraycopy(content, position, pack, 0, pack.length);
                dataPacketList.add(sliceCmd(order, packageSum, cmd, pack));
            }

            position += currentPackSize;
            remain -= currentPackSize;

        }
        return dataPacketList;
    }

    private static YGBleDataPacket sliceCmd(byte order, byte packageSum, byte cmd, byte[] data) {
        JSONObject jsonObject = new JSONObject();
        try {
            if (order <= 1) {
                jsonObject.put("type", "restart");
                jsonObject.put("offset", 0);
            } else if (order == packageSum) {
                jsonObject.put("type", "end");
                jsonObject.put("offset", (order-2) * YGBleDataPacket.REAL_SIZE + YGBleDataPacket.REAL_SIZE/*+ data.length*/);
            } else {
                jsonObject.put("type", "continued");
                jsonObject.put("offset", (order-2) * YGBleDataPacket.REAL_SIZE + YGBleDataPacket.REAL_SIZE);
            }
            jsonObject.put("data", new String(data));
            LogUtils.i("slice Cmd : " + jsonObject.toString());
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return new YGBleDataPacket(jsonObject.toString().getBytes());
    }

    private static byte getCheckSum(byte cmd, byte[] contentSlice) {
        byte sum = cmd;

        if (contentSlice != null) {
            for (int i = 0; i < contentSlice.length; i++) {
                sum += contentSlice[i];
            }
        }
        return sum;
    }


    public boolean unPackageData(Cmd cmd, byte[] packData) {
        boolean isValid = YGBleDataPacket.validateSlicePackage(packData);

        if (!isValid) {
            return false;
        }
        cmd.setContent(packData);
        return true;
    }

}
